import type { IPostComment, IPostCommentReply } from '@/interfaces';
import { type ChangeEvent, useContext, useEffect, useState } from 'react';
import { useInfiniteQuery, useMutation } from '@tanstack/react-query';
import useToast, { LoginReminderContent } from '@/hooks/useToast';
import { createReply, queryAllReplyByCommentId } from '@/services/api';
import sanitizeHtml from 'sanitize-html';
import Image from 'next/image';
import { getUserAvatar, toRelativeTime } from '@/lib/tool';
import Link from 'next/link';
import classNames from 'classnames';
import Reply from '@/app/[locale]/posts/[id]/reply';
import ContentHtml from '@/app/[locale]/common/content/html';
import { PostIdPageContext } from '@/contexts/post-id';
import { AppContext } from '@/contexts/app';
import Spinner from '@/app/[locale]/component/spinner/spinner';

export default function Comment({
  commentItem,
  commentIndex,
}: {
  commentItem: IPostComment;
  commentIndex: number;
}) {
  const context = useContext(PostIdPageContext)!;
  const {
    source: { path },
    translatedFields,
  } = context;
  const appContext = useContext(AppContext);
  const metadata = appContext.metadata!;
  const env = metadata.env;
  const [replyContent, setReplyContent] = useState('');
  const { show } = useToast();
  const [pages, setPages] = useState<IPostCommentReply[]>(commentItem.content);
  const queryKey = [
    '/forum',
    '/replies',
    '/comments',
    commentItem.comment.id,
    'infinite',
  ];

  const replyQuery = useInfiniteQuery(
    queryKey,
    async (context) => {
      return (await queryAllReplyByCommentId({
        id: context.queryKey[3],
        query: context.pageParam,
      })) as IPostComment;
    },
    {
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (!firstPage.pageable.previous) {
          return;
        }
        return {
          page: Math.max(firstPage.pageable.page - 1, 0),
        };
      },
      getNextPageParam: (lastPage) => {
        if (!lastPage.pageable.next) {
          return;
        }
        return {
          page: Math.min(lastPage.pageable.page + 1, lastPage.pageable.pages),
        };
      },
      initialData: () => {
        return {
          pages: [commentItem],
          pageParams: [{ page: 0 }],
        };
      },
    },
  );

  const createReplyMutation = useMutation(createReply);

  useEffect(() => {
    if (replyQuery.data) {
      setPages(
        replyQuery.data.pages
          .flatMap((item) => item.content)
          .map((item) => {
            item.reply._createdOnText = toRelativeTime(item.reply.createdOn);
            return item;
          }),
      );
    }
  }, [replyQuery.data]);

  async function onClickPostReply() {
    try {
      if (!path.user) {
        show({
          title: translatedFields.notLoggedInPrompt,
          content: <LoginReminderContent />,
        });
        return;
      }

      const _replyContent = replyContent.trim();
      if (!_replyContent) {
        show({
          type: 'DANGER',
          message: translatedFields.replyContentEmptyError,
        });
        return;
      }

      const content = sanitizeHtml(_replyContent);
      if (!content) {
        show({
          type: 'DANGER',
          message: translatedFields.replyContentEmptyError,
        });
        return;
      }

      const commentId = commentItem.comment.id;
      await createReplyMutation.mutateAsync({
        data: {
          commentId,
          content,
        },
      });

      await replyQuery.refetch({ throwOnError: true });

      setReplyContent('');
      show({
        type: 'SUCCESS',
        message: translatedFields.replyCompleted,
      });
    } catch (e) {
      createReplyMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickLoadMore() {
    try {
      await replyQuery.fetchNextPage();
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onChangeReplyContent(e: ChangeEvent<HTMLTextAreaElement>) {
    setReplyContent(e.target.value);
  }

  return (
    <PostIdPageContext.Provider value={{ ...context, queryKey }}>
      <div className="row mx-0">
        <div className="col-12 col-lg-2 px-0">
          <div
            className="card h-100 border-0 rounded-0 vstack gap-2"
            style={{
              borderBottomLeftRadius: '0.376rem !important',
            }}
          >
            <div
              className="align-self-center my-4"
              style={{ width: 128, height: 128 }}
            >
              <Image
                className="rounded-circle card-img-top object-fit-contain"
                src={getUserAvatar(commentItem.user, metadata).mediumAvatarUrl}
                alt={commentItem.user.alias}
                width={128}
                height={128}
                placeholder="blur"
                blurDataURL={env.APP_BLUR_DATA_URL}
              />
            </div>
            <div className="card-body align-self-center text-center">
              <h5 className="card-title">
                <Link
                  href={`/users/${commentItem.user.id}`}
                  className="link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
                >
                  {commentItem.user.alias}
                </Link>
              </h5>

              <p className="card-text my-3">
                {commentItem.user.roles
                  .filter((item) => !item.hide)
                  .map((item) => item.name)
                  .join(' / ')}
              </p>
            </div>
            <div className="card-footer border-top-0 border-bottom border-secondary border-opacity-10">
              <small
                className="text-secondary"
                title={translatedFields.contentUpdatedTime}
              >
                {translatedFields.lastUpdated}&nbsp;
                <time dateTime={commentItem.comment.createdOn}>
                  {commentItem.comment._createdOnText}
                </time>
              </small>
            </div>
          </div>
        </div>
        <div className="col col-lg-10 px-0">
          <div
            className="card border-0 border-secondary border-opacity-10 rounded-0 h-100 border-bottom"
            style={{
              borderBottomRightRadius: '0.376rem !important',
            }}
          >
            <div className="card-body">
              <div className={classNames('position-absolute top-0 end-0 mx-3')}>
                <small
                  title={`${translatedFields.currentFloorNumber} ${
                    commentIndex + 1
                  }`}
                  className="text-secondary user-select-none"
                >
                  {commentIndex + 1}
                </small>
              </div>

              <ContentHtml
                classs="content-layer-pc mt-3 mb-7"
                content={commentItem.comment.content}
              />

              {path.user && (
                <div className="my-7">
                  <div className="text-secondary">
                    <a
                      className="user-select-none text-secondary link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
                      data-bs-toggle="collapse"
                      href={`#yw-c-${commentItem.comment.id}`}
                      role="button"
                      aria-expanded="false"
                      aria-controls={`yw-c-${commentItem.comment.id}`}
                    >
                      {translatedFields.reply}
                    </a>
                  </div>

                  <div
                    className="collapse"
                    id={`yw-c-${commentItem.comment.id}`}
                  >
                    <div>
                      <textarea
                        className="form-control my-3"
                        rows={4}
                        placeholder={translatedFields.enterReply}
                        name="replyContent"
                        value={replyContent}
                        onChange={onChangeReplyContent}
                      ></textarea>
                      <button
                        disabled={
                          createReplyMutation.isLoading || !replyContent
                        }
                        onClick={onClickPostReply}
                        type="button"
                        className="btn btn-outline-primary my-3 w-100"
                      >
                        {createReplyMutation.isLoading ? (
                          <Spinner classs="me-2" />
                        ) : (
                          <i className="bi bi-cursor me-2"></i>
                        )}
                        {translatedFields.postReply}
                      </button>
                    </div>
                  </div>
                </div>
              )}

              {pages.length > 0 && (
                <div className="vstack gap-4 my-5">
                  {pages.map((item, index) => {
                    return (
                      <Reply
                        key={item.reply.id}
                        replyItem={item}
                        replyIndex={index}
                        commentItem={commentItem}
                        commentIndex={commentIndex}
                      />
                    );
                  })}
                </div>
              )}

              {replyQuery.hasNextPage && (
                <LoadMoreReplyBtn
                  isLoading={replyQuery.isLoading}
                  onClickLoadMore={onClickLoadMore}
                />
              )}
            </div>
          </div>
        </div>
      </div>
    </PostIdPageContext.Provider>
  );
}

const LoadMoreReplyBtn = ({
  onClickLoadMore,
  isLoading,
}: {
  onClickLoadMore: () => void;
  isLoading: boolean;
}) => {
  return (
    <div className="row mx-0">
      <div className="col px-0">
        <div className="card border-0">
          <div className="card-body">
            <button
              onClick={onClickLoadMore}
              disabled={isLoading}
              type="button"
              className="btn rounded-pill text-secondary-emphasis w-100"
            >
              {isLoading ? <Spinner /> : <i className="bi bi-three-dots"></i>}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};
